﻿using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace YOLO4DMF {
    public partial class Form1 : Form {
        // display image
        Image img;
        const int rows = 550, cols = 900, channals = 3;
        byte[] img_data = new byte[rows * cols * channals * 10];
        ulong img_size = new ulong();
        uint sleep_ms;

        // perspective transform
        bool calibrate_finished = false;
        bool transIsValid = false;

        // detection & tracking
        uint droplet_num;
        uint[] results = new uint[1024];

        Thread background_worker = null;

        void init() {
            background_worker = new Thread(do_work);
            background_worker.IsBackground = true;
            background_worker.Start();
        }

        public void do_work() {
            while (true) {
                if (background_worker_start) {
                    state = readFrame(sleep_ms);
                    if (!state) {
                        MessageBox.Show("视频播放结束!", "提示");
                        background_worker_start = false;
                        continue;
                    }
                }
                else {
                    Thread.Sleep(100);
                    continue;
                }

                if (transIsValid) {
                    perspectiveTransform();
                }

                switch (task) {
                    case TASK.NONE:
                        break;

                    case TASK.CALIBRATE:
                        for (int i = 0; i < selectedAnchorNum; ++i) {
                            drawCross(anchors[2 * i], anchors[2 * i + 1], 20, 2);
                        }
                        if (calibrate_finished) {
                            state = getTransformMatrix(ref anchors[0]);
                            if (state) {
                                Console.WriteLine("Calibrate successfully");
                                transIsValid = true;
                                data.CalibrationData.Default.isValid = true;
                                data.CalibrationData.Default.x1 = anchors[0];
                                data.CalibrationData.Default.y1 = anchors[1];
                                data.CalibrationData.Default.x2 = anchors[2];
                                data.CalibrationData.Default.y2 = anchors[3];
                                data.CalibrationData.Default.x3 = anchors[4];
                                data.CalibrationData.Default.y3 = anchors[5];
                                data.CalibrationData.Default.x4 = anchors[6];
                                data.CalibrationData.Default.y4 = anchors[7];
                                data.CalibrationData.Default.Save();
                                btn_cali_exit_Click(null, null);
                            }
                            else {
                                Console.WriteLine("re-calibrate");
                                DialogResult dr = MessageBox.Show("锚点坐标不符合，请重新锚定", "重新锚定");
                                calibrate_finished = false;
                            }
                        }
                        break;

                    case TASK.DETECT:
                        state = detectDroplets(out droplet_num);
                        if (state) {
                            tbox_number.Text = Convert.ToString(droplet_num);
                        }
                        else {
                            Console.WriteLine("detection failed");
                        }
                        break;

                    case TASK.INIT_TRACK:
                        Console.Write("initTracker ... ");
                        state = initTracker();
                        if (state) {
                            state = readLabelMatrix("../config/labelMatrix.txt");
                            if(!state) throw new Exception("ERROR:\n" +
                                "file: ../config/labelMatrix.txt\n" +
                                "labelMatrix is not exist!");
                            task = TASK.TRACK;
                            Console.WriteLine("Done.");
                        }
                        else {
                            Console.WriteLine("Failed.");
                        }
                        break;

                    case TASK.TRACK:
                        state = trackDroplets(out droplet_num, ref results[0]);
                        if (state) {
                            tbox_number.Text = Convert.ToString(droplet_num);
                            tbox_results.Clear();
                            for (int i = 0; results[i] != 0xff; i += 2) {
                                var line = String.Format("  droplet[{0}]: {1}\n", results[i], results[i + 1]);
                                tbox_results.AppendText(line);
                            }
                        }
                        else {
                            Console.WriteLine("tracking failed");
                            continue;
                        }
                        break;
                }

                state = getResultImage(ref img_data[0], out img_size);
                if (state) {
                    img = Image.FromStream(new MemoryStream(img_data, 0, (int)img_size));
                    picturebox.Image = img;
                }
            }
        }
    }
}